package com.sdgakj.rest;

import com.alibaba.fastjson.JSONObject;
import com.allinpay.ets.client.PaymentResult;
import com.sdgakj.dto.base.ResCode;
import com.sdgakj.dto.base.ResResult;
import com.sdgakj.entity.Order;
import com.sdgakj.entity.OrderPay;
import com.sdgakj.entity.User;
import com.sdgakj.enums.EnumPayType;
import com.sdgakj.repository.OrderPayDao;
import com.sdgakj.service.ServiceException;
import com.sdgakj.service.order.OrderPayService;
import com.sdgakj.service.order.OrderService;
import com.sdgakj.service.user.UserService;
import com.sdgakj.utils.DateUtil;
import com.sdgakj.utils.Md5Util;
import com.sdgakj.utils.NetworkUtil;
import com.sdgakj.utils.PropUtil;
import com.sdgakj.utils.alipay.util.AlipayNotify;
import com.sdgakj.utils.tencent.WXPay;
import com.sdgakj.utils.tencent.common.Configure;
import com.sdgakj.utils.tencent.common.RandomStringGenerator;
import com.sdgakj.utils.tencent.common.Signature;
import com.sdgakj.utils.tencent.common.XMLParser;
import com.sdgakj.utils.tencent.protocol.order_protocol.UnifiedOrderReqData;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springside.modules.web.MediaTypes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@RestController
@RequestMapping(value = "/api/v1/orderPay")
public class OrderPayRestController {

    private static Logger logger = LoggerFactory.getLogger(OrderPayRestController.class);

    @Autowired
    private OrderPayDao orderPayDao;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private UserService userService;

    /**
     * @return String @throws
     * @Title: alipay
     * @Description: 支付宝支付回调
     */
    /*@RequestMapping(value = "aliPayResultNotify", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public void orderPayResultNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("aliPayResultNotify start");
        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();
            for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                String name = (String) iter.next();
                String[] values = (String[]) requestParams.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
                }
                params.put(name, valueStr);
            }

            // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            // 卖家账户

            String buyer_email = new String(request.getParameter("buyer_email").getBytes("ISO-8859-1"), "UTF-8");
            // 商户订单号

            String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 支付宝交易号

            String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

            // 交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
            if (AlipayNotify.verify(params)) {
                // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
                Map<String, Object> body = new HashMap<String, Object>();
                // if (AlipayNotify.verify(params)) {// 验证成功
                // 请在这里加上商户的业务逻辑程序代码
                body.put("order_id", out_trade_no);
                body.put("out_order_id", out_trade_no);
                body.put("trade_no", trade_no);
                body.put("account", buyer_email);
                logger.info("out_trade_no:" + out_trade_no + "out_trade_no:" + out_trade_no + "trade_no:" + trade_no
                        + "buyer_email:" + buyer_email);
                if (trade_status.equals("TRADE_FINISHED")) {
                    body.put("trade_status", "TRADE_SUCCESS");
                } else if (trade_status.equals("TRADE_SUCCESS")) {
                    body.put("trade_status", "TRADE_SUCCESS");
                } else {
                    body.put("trade_status", "TRADE_FAIL");
                }
                orderService.orderPayResultNotify(request, response, body, EnumPayType.ALIPAY.getCode());

                logger.info("aliPayResultNotify check success!!!!!!!!");
            }
            logger.info("aliPayResultNotify end");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/

    @RequestMapping(value = "/wxPayinsertOrder", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8)
    public ResResult wxPayinserOrder(@RequestParam(value = "userId",defaultValue = "1") Long userId,
                                  @RequestParam(value = "donationId",defaultValue = "donationId")Long donationId,
                                  Model model){
        ResResult result = new ResResult();
        User user = new User();
        OrderPay orderPay = new OrderPay();
        orderPay.setDonationId(donationId);
        orderPay.setUserId(userId);
        orderPay.setType(2);
        orderPay.setState(0);
        orderPay.setAmount(0.00);
        orderPay.setPayTime(new Date());
        User openid = userService.getUserById(userId);
        orderPay.setOpenid(openid.getOpenid());
        orderPay = orderPayDao.save(orderPay);
        result.setData(orderPay);
        return result;

    }





    /****
     * @return String @throws
     * @Title: wxpay
     * @Description: 微信支付回调  统一下单
     */
    @RequestMapping(value = "wxPayUnifiedOrder", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public ResResult wxPayResultNotify(HttpServletRequest request,
                                       @RequestParam(value = "userId", defaultValue = "1") Long userId,
                                       @RequestParam(value = "orderpayid")Long id,
                                       @RequestParam(value = "openId", defaultValue = "ozgZWwHaoVFx52f1dxIHZCIKF_eI")String openId,
                                       @RequestParam(value = "donationId",defaultValue = "1") Long donationId,
                                       @RequestParam(value = "moneyNum") Double moneyNum,
                                       @RequestParam(value = "tradeType", defaultValue = "JSAPI") String tradeType) {
        logger.info("wxPayUnifiedOrder start");
        ResResult result = new ResResult();
        try {
            User user = new User();
            if (!"0".equals(userId)) {
                user = userService.getUserById(userId);
                if (user == null || user.getId() == 0) {
                    result.setResCode(ResCode.NEED_USERID.getResCode());
                    result.setResMsg(ResCode.NEED_USERID.getResMsg());
                    return result;
                }
                if (user.getOpenid() == null || "".equals(user.getOpenid())) {
                    result.setResCode(ResCode.NEED_OPENID.getResCode());
                    result.setResMsg(ResCode.NEED_OPENID.getResMsg());
                    return result;
                }
            }
            OrderPay orderPay = orderPayService.getById(id);
            String startDateString = DateUtil.formatDateToString(new Date(), "yyyyMMddHHmmss");
            Calendar expireDate = Calendar.getInstance();
            expireDate.setTime(new Date());
            expireDate.add(Calendar.DAY_OF_MONTH, 1);
            String expireDateString = DateUtil.formatDateToString(expireDate.getTime(), "yyyyMMddHHmmss");
            String nonceStr = RandomStringGenerator.getRandomStringByLength(32);
            //orderPay.getId().toString()
            UnifiedOrderReqData unifiedOrderReqData = new UnifiedOrderReqData("云谱捐赠支付", "", "",orderPay.getId().toString(), (int) (moneyNum * 100), "", NetworkUtil.getIpAddress(request), startDateString, expireDateString, "", tradeType, nonceStr,user.getOpenid());
            Map<String, String>  map = XMLParser.parseXml(WXPay.requestUnifiedOrderService(unifiedOrderReqData));
            String appid = map.get("appid");
            String mch_id = map.get("mch_id");
            String prepay_id = map.get("prepay_id");
            orderPayService.updatePrepayOrder(orderPay, prepay_id, nonceStr);
            logger.info("return_code:" + map.get("return_code") + ";result_code" + map.get("result_code") + "prepay_id:" + map.get("prepay_id"));
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("appId", appid);
            resultMap.put("timeStamp", System.currentTimeMillis() / 1000 + "");
            resultMap.put("nonceStr", nonceStr);
            resultMap.put("package", "prepay_id="+prepay_id);
            resultMap.put("signType", "MD5");
            resultMap.put("paySign", Signature.getSign(resultMap));
            result.setData(resultMap);
            logger.info("wxPayResultNotify end");
        } catch (Exception e) {
            e.printStackTrace();
            result.setResCode(1);
            result.setResMsg("统一下单，业务异常！");
            return result;
        }
        return result;
    }
    /**
     * @return String @throws
     * @Title: wxpay
     * @Description: 微信支付回调
     */
    @RequestMapping(value = "wxPayResult", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public void wxPayResult(HttpServletRequest request, HttpServletResponse response,@RequestParam(value = "orderpayid")Long id){
        logger.info("  start");
        try {
            Map<String, Object> resultMap = XMLParser.parseXml(request);
            String openid = (String) resultMap.get("openid");
            String out_trade_no = (String) resultMap.get("out_trade_no");
            String total_fee = (String) resultMap.get("total_fee");
            OrderPay orderPay = orderPayService.getById(Long.parseLong(out_trade_no));
            orderPay.setState(2);
            Double amount = Double.parseDouble(total_fee);
            amount = (double)Math.round(amount)/100;
            orderPay.setAmount(amount);
            orderPayDao.save(orderPay);

            logger.info("wxPayResultNotify end");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * @return String @throws
     * @Title: wxpay
     * @Description: 微信支付回调
     */
    @RequestMapping(value = "wxPayResultNotify", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public void wxPayResultNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("  start");
        try {
            Map<String, Object> resultMap = XMLParser.parseXml(request);
            String openid = (String) resultMap.get("openid");
            String out_trade_no = (String) resultMap.get("out_trade_no");
            // 微信交易号
            String trade_no = (String) resultMap.get("transaction_id");
            // 交易状态
            String total_fee = (String) resultMap.get("total_fee");
            OrderPay orderPay = orderPayService.getById(Long.parseLong(out_trade_no));
            orderPay.setState(2);
            orderPay.setAmount(Double.parseDouble(total_fee)/100);
            orderPayDao.save(orderPay);
            String result_code = (String) resultMap.get("result_code");
            if (Signature.checkIsSignValidFromMap(resultMap)) {
                // 获取微信的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
                Map<String, Object> body = new HashMap<String, Object>();
                // if (AlipayNotify.verify(params)) {// 验证成功
                // 请在这里加上商户的业务逻辑程序代码
                body.put("order_id", out_trade_no);
                body.put("out_order_id", out_trade_no);
                body.put("trade_no", trade_no);
                body.put("account", trade_no);
                if (result_code.equals("SUCCESS")) {
                    body.put("trade_status", "TRADE_SUCCESS");
                } else {
                    body.put("trade_status", "TRADE_FAIL");
                }
                orderService.orderPayResultNotify(request, response, body, EnumPayType.WXPAY.getCode());

                logger.info("wxPayResultNotify check success!");
            }
            logger.info("wxPayResultNotify end");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 订单取消退款
     * 
     * @param orderId
     * @return
     */
    @RequestMapping(value = "/getOrderPrice", method = RequestMethod.GET, produces = MediaTypes.JSON_UTF_8)
    public ResResult getOrderPrice(@RequestParam(value = "orderId", defaultValue = "0") Long orderId) {
        logger.info("orderId:" + orderId);
        ResResult result = new ResResult();
        try {
            result.setData(orderService.getOrderPrice(orderId));
        } catch (ServiceException e) {
            result.setResCode(e.getResCode());
            logger.info("I-[获取订单价格]业务错误", e);
        } catch (Exception e) {
            result.setResCode(ResCode.ERROR);
            logger.error("I-[获取订单价格]程序异常", e);
        }
        return result;
    }



    /**
     *
     * @Title: unionpay
     * @Description: 通联支付回调
     *
    StringUtil.appendSignPara(bufSignSrc, "merchantId", paymentResult.getMerchantId());
    StringUtil.appendSignPara(bufSignSrc, "version", paymentResult.getVersion());
    StringUtil.appendSignPara(bufSignSrc, "language", paymentResult.getLanguage());
    StringUtil.appendSignPara(bufSignSrc, "signType", paymentResult.getSignType());
    StringUtil.appendSignPara(bufSignSrc, "payType", paymentResult.getPayType());
    StringUtil.appendSignPara(bufSignSrc, "issuerId", paymentResult.getIssuerId());
    StringUtil.appendSignPara(bufSignSrc, "paymentOrderId", paymentResult.getPaymentOrderId());
    StringUtil.appendSignPara(bufSignSrc, "orderNo", paymentResult.getOrderNo());
    StringUtil.appendSignPara(bufSignSrc, "orderDatetime", paymentResult.getOrderDatetime());
    StringUtil.appendSignPara(bufSignSrc, "orderAmount", String.valueOf(paymentResult.getOrderAmount()));
    StringUtil.appendSignPara(bufSignSrc, "payDatetime", paymentResult.getPayDatetime());
    StringUtil.appendSignPara(bufSignSrc, "payAmount", String.valueOf(paymentResult.getPayAmount()));
    StringUtil.appendSignPara(bufSignSrc, "ext1", paymentResult.getExt1());
    StringUtil.appendSignPara(bufSignSrc, "ext2", paymentResult.getExt2());
    StringUtil.appendSignPara(bufSignSrc, "payResult", paymentResult.getPayResult());
    StringUtil.appendSignPara(bufSignSrc, "errorCode", paymentResult.getErrorCode());
    StringUtil.appendLastSignPara(bufSignSrc, "returnDatetime", paymentResult.getReturnDatetime());
     *
     */
    @RequestMapping(value = "/unionPayResultNotify", method = RequestMethod.POST)
    public void unionPayResultNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("unionPayResultNotify start");
        try {

            //打印参数
            showParameter(request.getParameterMap());

            Map<String, Object> body = new HashMap<String, Object>();

            String merchantId = request.getParameter("merchantId");
            String version = request.getParameter("version");
            String language = request.getParameter("language");
            String signType = request.getParameter("signType");
            String payType = request.getParameter("payType");
            String issuerId = request.getParameter("issuerId");
            String paymentOrderId = request.getParameter("paymentOrderId");// 通联支付订单ID
            String orderNo = request.getParameter("orderNo");  //商户内部订单ID
            String orderDatetime = request.getParameter("orderDatetime");
            String orderAmount = request.getParameter("orderAmount");
            String payDatetime = request.getParameter("payDatetime");
            String payAmount = request.getParameter("payAmount");
            String payResult = request.getParameter("payResult");
            String ext1  = request.getParameter("ext1");
            String ext2  = request.getParameter("ext2");
            String errorCode = request.getParameter("request");
            String returnDatetime = request.getParameter("returnDatetime");
            String signMsg = request.getParameter("signMsg");

            // 验签是商户为了验证接收到的报文数据确实是支付网关发送的。
            // 构造订单结果对象，验证签名。
            PaymentResult paymentResult = new PaymentResult();
            paymentResult.setMerchantId(merchantId);
            paymentResult.setVersion(version);
            paymentResult.setLanguage(language);
            paymentResult.setSignType(signType);
            paymentResult.setPayType(payType);
            paymentResult.setIssuerId(issuerId);
            paymentResult.setPaymentOrderId(paymentOrderId);
            paymentResult.setOrderNo(orderNo);
            paymentResult.setOrderDatetime(orderDatetime);
            paymentResult.setOrderAmount(orderAmount);
            paymentResult.setPayDatetime(payDatetime);
            paymentResult.setPayAmount(payAmount);
            paymentResult.setPayResult(payResult);
            paymentResult.setExt1(ext1);
            paymentResult.setExt2(ext2);
            paymentResult.setErrorCode(errorCode);
            paymentResult.setReturnDatetime(returnDatetime);

            // signMsg为服务器端返回的签名值。
            paymentResult.setSignMsg(signMsg);
            // 验证签名：返回true代表验签成功；否则验签失败。
            boolean verifyResult = true;

            // signType为"1"时，必须设置证书路径。
            if ("1".equals(signType)) {
                String cerFilePath = PropUtil.getInstance().get("allinpay.cer.path");
                String certPath = this.getClass().getResource(cerFilePath).getPath();
                if (SystemUtils.IS_OS_WINDOWS) {
                    if (certPath.startsWith("/")) {
                        certPath = StringUtils.stripStart(certPath, "/");
                    }
                }
                logger.info("certPath:" + certPath);
                paymentResult.setCertPath(certPath);
                verifyResult = paymentResult.verify();  //a=b&xxx  signType
            }
            logger.info("allinpay_notify:" + JSONObject.toJSONString(paymentResult));
            if (verifyResult) {// 服务器签名验证成功
                // 请在这里加上商户的业务逻辑程序代码
                // 获取通知返回参数，可参考接口文档中通知参数列表(以下仅供参考)
                String transStatus = request.getParameter("payResult");// 交易状态

                body.put("order_id", orderNo);
                body.put("out_order_id", orderNo);
                //通联订单号
                body.put("trade_no", paymentOrderId);
                body.put("account",paymentOrderId);

                if (null != transStatus && "1".equals(transStatus)) {
                    // 交易处理成功
                    body.put("trade_status", "TRADE_SUCCESS");
                } else {
                    body.put("trade_status", "TRADE_FAIL");
                }
                orderService.orderPayResultNotify(request, response, body, EnumPayType.ALLINPAY.getCode());
                logger.info("allinpay  success");
            }
            logger.info("unionPayResultNotify end");
        } catch (Exception e) {
            logger.error("通联支付error",e);
        }
    }



    /**
     * 打印第三方支付异步回调的参数信息
     * @param paramMap
     */
    public void  showParameter(Map<String, String[]> paramMap) {
        Iterator<Map.Entry<String, String[]>> it = paramMap.entrySet().iterator();
        StringBuilder stringBuilder = new StringBuilder();
        while (it.hasNext()) {
            Map.Entry<String, String[]> entry = it.next();
            StringBuilder values = new StringBuilder();
            for (String v : entry.getValue()) {
                values.append(v);
                values.append(" ");
            }
            stringBuilder.append(entry.getKey());
            stringBuilder.append("=");
            stringBuilder.append(values.toString());
            stringBuilder.append(",");
        }
        logger.info("pay_param:" + stringBuilder.toString());
    }


//
//    @RequestMapping(value = "/a1", method = RequestMethod.GET)
//    public void test(HttpServletRequest request) {
//        String certPath = request.getSession().getServletContext().getRealPath(request.getRequestURI());
//        logger.info(certPath);
//        String uri = request.getRequestURI().replace("/", File.separator);
//        logger.info(uri);
//        certPath = certPath.replace(uri, "");
//        logger.info(certPath);
//        certPath = certPath + "/TLCert.cer";
//        logger.info(certPath);
//
//        String file = this.getClass().getResource("/cer/TLCert-test.cer").getPath();
//        if (SystemUtils.IS_OS_WINDOWS) {
//            if (file.startsWith("/")) {
//                file = StringUtils.stripStart(file,"/");
//            }
//        }
//        logger.info(file + ":");
//
//    }


}
